package com.wangzhixuan.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wangzhixuan.commons.result.Tree;
import com.wangzhixuan.commons.shiro.ShiroUser;
import com.wangzhixuan.mapper.ResourceMapper;
import com.wangzhixuan.mapper.RoleMapper;
import com.wangzhixuan.mapper.RoleResourceMapper;
import com.wangzhixuan.mapper.UserRoleMapper;
import com.wangzhixuan.model.Resource;
import com.wangzhixuan.model.vo.ResourceVo;
import com.wangzhixuan.service.IResourceService;
import org.apache.commons.beanutils.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * Resource 表数据服务层接口实现类
 */
@Service
public class ResourceServiceImpl extends ServiceImpl<ResourceMapper, Resource> implements IResourceService {
    private static final int RESOURCE_MENU = 0; // 菜单

    @javax.annotation.Resource
    private ResourceMapper resourceMapper;
    @javax.annotation.Resource
    private UserRoleMapper userRoleMapper;
    @javax.annotation.Resource
    private RoleMapper roleMapper;
    @javax.annotation.Resource
    private RoleResourceMapper roleResourceMapper;

    @Override
    public List<ResourceVo> selectAll() {
        return baseMapper.selectAll();
    }

    private List<Tree> selectAllByStatus(Integer status) {
        Resource resource = new Resource();
        if (status != null) {
            resource.setStatus(status);
        }
        QueryWrapper<Resource> wrapper = new QueryWrapper<Resource>(resource);
        wrapper.orderBy(true, true, "seq");
        List<Resource> resources = resourceMapper.selectList(wrapper);
        return buildTree(resources);
    }

    private List<Resource> selectByType(Integer type) {
        Resource resource = new Resource();
        resource.setResourceType(type);
        resource.setStatus(0);
        QueryWrapper<Resource> wrapper = new QueryWrapper<>(resource);
        wrapper.orderBy(true, true, "seq");
        return resourceMapper.selectList(wrapper);
    }

    @Override
    public List<Tree> selectAllMenu() {
        List<Tree> trees = new ArrayList<Tree>();
        // 查询所有菜单
        List<Resource> resources = this.selectByType(RESOURCE_MENU);
        if (resources == null) {
            return trees;
        }
        for (Resource resource : resources) {
            Tree tree = new Tree();
            tree.setId(resource.getId());
            tree.setPid(resource.getPid());
            tree.setText(resource.getName());
            tree.setIconCls(resource.getIcon());
            tree.setAttributes(resource.getUrl());
            tree.setState(resource.getOpened());
            trees.add(tree);
        }
        return trees;
    }

    @Override
    public List<Tree> selectAllTree() {
        // 获取所有的资源 tree形式，展示
        return this.selectAllByStatus(0);
    }

    @Override
    public List<Tree> selectTree(ShiroUser shiroUser) {
        List<Tree> trees = new ArrayList<Tree>();
        // shiro中缓存的用户角色
        Set<String> roles = shiroUser.getRoles();
        if (roles == null) {
            return trees;
        }
        // 如果有超级管理员权限
        if (roles.contains("admin")) {
            List<Resource> resourceList = this.selectByType(RESOURCE_MENU);
            return buildTree(resourceList);
        }
        // 普通用户
        List<Long> roleIdList = userRoleMapper.selectRoleIdListByUserId(shiroUser.getId());
        if (roleIdList == null) {
            return trees;
        }
        List<Resource> resourceLists = roleMapper.selectResourceListByRoleIdList(roleIdList);
        if (resourceLists == null) {
            return trees;
        }
        return buildTree(resourceLists);
    }

    private List<Tree> buildTree(List<Resource> resourceList) {
        List<Tree> trees = new ArrayList<>();
        if (resourceList == null) {
            return trees;
        }
        resourceList.forEach(resource -> {
            if (resource.getPid() == null || resource.getPid() == 0) {
                Tree tree = convertTree(resource);
                tree.setChildren(buildChildren(resourceList, tree.getId()));
                trees.add(tree);
            }
        });
        return trees;
    }

    private List<Tree> buildChildren(List<Resource> resourceList, Long pid) {
        List<Tree> childrens = new ArrayList<>();
        resourceList.forEach(res -> {
            if (pid.equals(res.getPid())) {
                Tree tree = convertTree(res);
                tree.setChildren(buildChildren(resourceList, tree.getId()));
                childrens.add(tree);
            }
        });
        if(childrens.isEmpty()){
            return null;
        }
        return childrens;
    }

    private Tree convertTree(Resource resource) {
        Tree tree = new Tree();
        tree.setId(resource.getId());
        tree.setPid(resource.getPid());
        tree.setText(resource.getName());
        tree.setIconCls(resource.getIcon());
        tree.setAttributes(resource.getUrl());
        tree.setOpenMode(resource.getOpenMode());
        tree.setState(resource.getOpened());
        return tree;
    }

    @Override
    public boolean removeById(Serializable resourceId) {
        roleResourceMapper.deleteByResourceId(resourceId);
        return super.removeById(resourceId);
    }
}